/*
 * ClassStruct.cpp
 *
 *  Created on: 21/nov/2010
 *      Author: computer
 */

#include "ClassStruct.h"
#include "Null.h"
#include "CallInstruction.h"

namespace TreeExpression {

ClassStruct::ClassStruct(const std::string& _name) : FlowExpression(), publicContext(new Context(_name)), protectedContext(new Context(_name)), privateContext(new Context(_name)), name(_name) { }

ClassStruct::ClassStruct(const ClassStruct& copy) : Expression(copy), FlowExpression(copy), publicContext(copy.publicContext), protectedContext(copy.protectedContext), privateContext(copy.privateContext), name(copy.name) { }

ClassStruct::~ClassStruct() { }

void ClassStruct::addDataMember(const AutoPointer<Expression>& expr, const std::string& _name, int _access) {
	/*std::list< DataMember >::iterator i;
	for (i = listDataMember.begin(); i != listDataMember.end(); ++i) {
		if (i->name == _name) {
			if (i->access >= _access) {
				i->data = expr;
				return;
			}
			else return;//TODO: error for private/protected
		}
	}
	listDataMember.push_back(DataMember(expr, _name, _access));*/
	if (_access == PUBLIC) {
		publicContext->addDefinition(_name, expr);
	}
	else if (_access == PROTECTED) {
		protectedContext->addDefinition(_name, expr);
	}
	else privateContext->addDefinition(_name, expr);
}

void ClassStruct::addMemberFunction(const AutoPointer<Expression>& expr, const std::string& _name, int _access) {
	/*std::list< MemberFunction >::iterator i;
	for (i = listMemberFunction.begin(); i != listMemberFunction.end(); ++i) {
		if (i->name == _name) {
			if (i->access >= _access) {
				i->data = expr;
				return;
			}
			else return;//TODO: error for private/protected
		}
	}
	listMemberFunction.push_back(MemberFunction(expr, _name, _access));*/
	if (_access == PUBLIC) {
		publicContext->addDeclaration(_name, expr);
	}
	else if (_access == PROTECTED) {
		protectedContext->addDeclaration(_name, expr);
	}
	else privateContext->addDeclaration(_name, expr);
}

AutoPointer<Expression> ClassStruct::getDataMember(const std::string& _name, int _access) const {
	/*std::list< DataMember >::const_iterator i;
	for (i = listDataMember.begin(); i != listDataMember.end(); ++i) {
		if (i->name == _name) {
			if (i->access >= _access) return i->data;
			else return AutoPointer<Expression>();//TODO: error for private/protected
		}
	}
	return AutoPointer<Expression>();*/
	/*if (_access == PUBLIC) {
		return publicContext->searchDefinitionInContext(_name);
	}
	else if (_access == PROTECTED) {
		AutoPointer<Expression> ris = publicContext->searchDefinitionInContext(_name);
		if (ris.isNull()) return protectedContext->searchDefinitionInContext(_name);
		else return ris;
	}
	else {
		AutoPointer<Expression> ris = publicContext->searchDefinitionInContext(_name);
		if (ris.isNull()) {
			AutoPointer<Expression> ris2 = protectedContext->searchDefinitionInContext(_name);
			if (ris.isNull()) return privateContext->searchDefinitionInContext(_name);
			else return ris2;
		}
		else return ris;
	}*/
}

std::list < AutoPointer<Expression> > ClassStruct::getMemberFunction(const std::string& _name, int _access) const {
	/*std::list< MemberFunction >::const_iterator i;
	for (i = listMemberFunction.begin(); i != listMemberFunction.end(); ++i) {
		if (i->name == _name) {
			if (i->access >= _access) return i->data;
			else return AutoPointer<Expression>();//TODO: error for private/protected
		}
	}
	return AutoPointer<Expression>();*/
	if (_access == PUBLIC) {
		return publicContext->searchDeclarationInContext(_name);
	}
	else if (_access == PROTECTED) {
		std::list < AutoPointer<Expression> > ris1 = publicContext->searchDeclarationInContext(_name);
		std::list < AutoPointer<Expression> > ris2 = protectedContext->searchDeclarationInContext(_name);
		ris1.splice(ris1.end(), ris2);
		return ris1;
	}
	else {
		std::list < AutoPointer<Expression> > ris1 = publicContext->searchDeclarationInContext(_name);
		std::list < AutoPointer<Expression> > ris2 = protectedContext->searchDeclarationInContext(_name);
		std::list < AutoPointer<Expression> > ris3 = privateContext->searchDeclarationInContext(_name);
		ris1.splice(ris1.end(), ris2);
		ris1.splice(ris1.end(), ris3);
		return ris1;
	}
}

AutoPointer<Expression> ClassStruct::call(const std::string& _nameCall, int /*_access*/, CopyPointer<Context>& context) {
	CopyPointer<Context> localContext( new Context(publicContext->join(protectedContext->join(*privateContext))));//TODO manage memory access
	AutoPointer<Expression> function(new CallInstruction(_nameCall));//TODO access
	function->setSon(this->getSon());//load the parameter
	//localContext->setBase(context);
	return function->eval(localContext);
}

std::string ClassStruct::toString() const {
	return name;//TODO
}

std::string ClassStruct::getHash() const {
	return name; //TODO
}

}
